package com.ruoyi.quartz.util;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ScheduleConstants;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.domain.SysJobLog;
import com.ruoyi.quartz.service.ISysJobLogService;

/**
 * 抽象quartz调用
 *
 * @author ruoyi
 */
public abstract class AbstractQuartzJob implements Job
{
    private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);

    /**
     * 线程本地变量
     */
    private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException
    {
    	Object ret=null;
        SysJob sysJob = new SysJob();
        BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
        try
        {
            before(context, sysJob);
            if (sysJob != null)
            {
                ret=doExecute(context, sysJob);
            }
            after(context, sysJob, ret, null);
        }
        catch (Exception e)
        {
            log.error("任务执行异常  - ：", e);
            after(context, sysJob, ret, e);
        }
    }

    /**
     * 执行前
     *
     * @param context 工作执行上下文对象
     * @param sysJob 系统计划任务
     */
    protected void before(JobExecutionContext context, SysJob sysJob)
    {
        threadLocal.set(new Date());
    }

    /**
     * 执行后
     *
     * @param context 工作执行上下文对象
     * @param sysJob 系统计划任务
     */
    protected void after(JobExecutionContext context, SysJob sysJob,Object retobj, Exception e)
    {
        Date startTime = threadLocal.get();
        threadLocal.remove();

        final SysJobLog sysJobLog = new SysJobLog();
        sysJobLog.setJobId(sysJob.getJobId());
        sysJobLog.setJobName(sysJob.getJobName());
        sysJobLog.setJobGroup(sysJob.getJobGroup());
        sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
        Map<String,Object> retmap=null;
        if(retobj instanceof Map)
        	retmap=(Map<String,Object>) retobj;
        if(retmap!=null && retmap.containsKey("flowID")) {
//        	从flowService返回的FlowContextVO中拿数据
        	sysJobLog.setFlowId((Long)retmap.get("flowID"));
        	if(retmap.containsKey("startDate"))
        		sysJobLog.setStartDate((Date)retmap.get("startDate")); 
        	if(retmap.containsKey("flowName"))
        		sysJobLog.setFlowName((String)retmap.get("flowName"));
        	if(retmap.containsKey("flowCode"))
        		sysJobLog.setFlowCode((String)retmap.get("flowCode"));
        	if(retmap.containsKey("successCnt"))
        		sysJobLog.setSuccessCnt((Long)retmap.get("successCnt"));
        	if(retmap.containsKey("errorCnt"))
        		sysJobLog.setErrorCnt((Long)retmap.get("errorCnt"));
        	if(retmap.containsKey("retCode")) {
	        	String retCode=(String)retmap.get("retCode");
	        	sysJobLog.setStatus(retCode.equals("200")?Constants.SUCCESS:Constants.FAIL);
        	}
        	sysJobLog.setEndDate(new Date());
        	sysJobLog.setTotalCnt(sysJobLog.getSuccessCnt()+sysJobLog.getErrorCnt());
//        	flow简报处理
        	if(retmap.containsKey("bulletinStr")) {
        		String bulletinStr=(String)retmap.get("bulletinStr");
        		sysJobLog.setJobMessage(bulletinStr);
        	}
        }else {
//        	flowService中指定返回对象,不是FlowContextVO
        	sysJobLog.setStartDate(startTime);
            sysJobLog.setEndDate(new Date());
            String msg="任务名称:[%s],调用返回: %s";
            if(retobj==null)
            	retobj="无返回!";
            msg=String.format(msg, sysJobLog.getJobName(),retobj);
            sysJobLog.setJobMessage(msg);
        }
//      耗用时间(毫秒)
        long runMs = sysJobLog.getEndDate().getTime() - sysJobLog.getStartDate().getTime();
        sysJobLog.setRunTime(runMs);
        
        if (e != null)
        {
            sysJobLog.setStatus(Constants.FAIL);
            String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
            sysJobLog.setExceptionInfo(errorMsg);
        }
        else
        {
//        	返回值 前面已经处理,这里不再处理
//            sysJobLog.setStatus(Constants.SUCCESS);
        }

        // 写入数据库当中
        SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
    }

    /**
     * 执行方法，由子类重载
     *
     * @param context 工作执行上下文对象
     * @param sysJob 系统计划任务
     * @throws Exception 执行过程中的异常
     */
    protected abstract Object doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
}
